﻿using Assets.Engine.ComputerGraphics.Bezier;
using DiamondSquare.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;


namespace Assets.Engine.SimpleArrow
{
    public class GroundQuiver : MonoBehaviour
    {
        public Material UIArrowMaterial;
        public GameObject Table;

        public static List<Path> ListPath = new List<Path>();

        private static GroundQuiver _gq;
        
        public void Awake()
        {
            GroundQuiver._gq = this;
        }

        public static void Init()
        {
            //VectorLine.canvas3D.name = "LineContainer3D";
        }

        internal void CreateTestPath(Vector3 origin)
        {
            int offset = 2;
            int startX = (int)(-_gq.Table.transform.position.x + 2);
            int endX = (int)(-_gq.Table.transform.position.x + _gq.Table.transform.localScale.x / 2 - 2);
            int startZ = (int)(-_gq.Table.transform.position.z + 2);
            int endZ = (int)(-_gq.Table.transform.position.z + _gq.Table.transform.localScale.z / 2 - 2);

            int sizeTestArrow = 4;

            float x;
            float z;
            Vector3[] checkpoints = new Vector3[sizeTestArrow];
            checkpoints[0] = new Vector3(origin.x, 0, origin.z);   //origin gameobject
            for (int i = 1; i < sizeTestArrow; i++)
            {
                do
                {
                    x = Randomize.NextFloat(startX, 0);
                    z = Randomize.NextFloat(startZ, endZ);
                } while ((x - offset > 0 && x < 128 + offset) || (z - offset > 0 && z < 128 + offset));

                checkpoints[i] = new Vector3(x, 1, z);
            }

            //GameObject newArrow = Instantiate(SplineExample);
            //newArrow.transform.position = new Vector3(0, 0, 0);
            //newArrow.name = "arrowTest";
            //newArrow.SetActive(true);
            //SetArrow(newArrow, checkpoints);

            CreatePath(checkpoints);

        }

        internal void CreateTestLink(Vector3 startPos, Vector3 endPos)
        {
            Vector3[] checkpoints = new Vector3[3];
            checkpoints[0] = startPos;

            float max_y = Mathf.Max(startPos.y, endPos.y);
            float distance = Vector3.Distance(startPos, endPos);

            checkpoints[1] = new Vector3(
                (startPos.x + endPos.x) / 2,
                max_y + distance / 3,
                (startPos.z + endPos.z) / 2
                );

            checkpoints[2] = endPos;

            CreateLink(checkpoints);

        }

        internal void CreatePath(Vector3[] points)
        {
            //GameObject newLink = new GameObject() { name = "path01" };

            //CurvySpline spline = CurvySpline.Create();
            //spline.Interpolation = CurvyInterpolation.Bezier;

            //foreach (Vector3 pos in points) spline.Add(pos);

            //SplinePathMeshBuilder spmb = SplinePathMeshBuilder.Create();
            //spmb.Spline = spline;
            //spmb.GetComponent<MeshRenderer>().material = UIArrowMaterial;
            //spmb.CapSegments = 8;
            //spmb.CapWidth = 0.3f;

            //spmb.Transform.parent = newLink.transform;
            //spline.Transform.parent = newLink.transform;
        }

        private void CreateLink(Vector3[] points)
        {
            //GameObject newLink = new GameObject() { name = "link01" };

            //CurvySpline spline = CurvySpline.Create();
            //spline.Interpolation = CurvyInterpolation.TCB;

            //foreach (Vector3 pos in points) spline.Add(pos);
            
            //SplinePathMeshBuilder spmb = SplinePathMeshBuilder.Create();
            //spmb.Spline = spline;
            //spmb.GetComponent<MeshRenderer>().material = UIArrowMaterial;
            //spmb.CapSegments = 8;
            //spmb.CapWidth = 0.3f;

            //spmb.Transform.parent = newLink.transform;
            //spline.Transform.parent = newLink.transform;

        }










        private void SetArrow(GameObject arrow, Vector3[] points)
        {
            //CurvySpline spline = arrow.GetComponent<CurvySpline>();

            //int cont = 0;

            //foreach (Vector3 pos in points)
            //{
            //    GameObject p1 = new GameObject() { name = "S" + cont };
            //    p1.transform.position = pos;
            //    p1.transform.rotation = Quaternion.identity;
            //    p1.AddComponent<CurvySplineSegment>();
            //    p1.transform.parent = arrow.transform;

            //    spline.Segments.Add(p1.GetComponent<CurvySplineSegment>());

            //    cont++;
            //}

        }

        public static Path CreateBezierPath(Transform origin, string name, int checkpointLenght = 8,
                                            float x_range = 200, float z_range = 200, float step = 0.2f)
        {
            Vector3[] checkpoints = new Vector3[checkpointLenght];
            float x, z;

            checkpoints[0] = new Vector3(origin.position.x, 0, origin.position.z);   //origin gameobject
            for (int i = 1; i < checkpointLenght; i++)
            {
                do
                {
                    x = Randomize.NextFloat(0 ,  - x_range);
                    z = Randomize.NextFloat(0 ,  - z_range);
                } while ( false );
                //} while (island.IsOnLand(x, z) == false ||
                //         island.IsInMainIsland(x, z) == false);

                checkpoints[i] = new Vector3(x, 1, z);
            }
            Vector3[] bezier = BezierPath.GetBezierApproximation(checkpoints, 256);  //interpolate checkpoint
            Path newArrow = GroundQuiver.CreatePath(bezier, name);                   //create graphic path
            newArrow.CreateCheckPoint(step);
            return newArrow;
        }

        public static Path CreateBezierPathOnTable(Transform origin, string name, 
                                                    int checkpointLenght = 8, 
                                                    float step = 0.2f)
        {

            int offset = 2;
            int startX = (int)( -_gq.Table.transform.position.x + 2 );
            int endX = (int)(-_gq.Table.transform.position.x + _gq.Table.transform.localScale.x - 2 );
            int startZ = (int)(-_gq.Table.transform.position.z + 2);
            int endZ = (int)(-_gq.Table.transform.position.z + _gq.Table.transform.localScale.z - 2);

            Vector3[] checkpoints = new Vector3[checkpointLenght];
            float x, z;

            checkpoints[0] = new Vector3(origin.position.x, 0, origin.position.z);   //origin gameobject
            for (int i = 1; i < checkpointLenght; i++)
            {
                do
                {
                    x = Randomize.NextFloat(startX, 0);
                    z = Randomize.NextFloat(startZ, endZ);
                } while ((x - offset > 0 && x < 128 + offset) || (z - offset > 0 && z < 128 + offset));

                checkpoints[i] = new Vector3(x, 1, z);
            }
            Vector3[] bezier = BezierPath.GetBezierApproximation(checkpoints, 256);  //interpolate checkpoint
            
            Path newArrow = GroundQuiver.CreatePath(bezier, name);                   //create graphic path
            newArrow.CreateCheckPoint(step);
            return newArrow;

            //return null;
        }

        private static Path CreatePath(Vector3[] listPoint, string name)
        {
            //UIArrow arrow = new UIArrow(listPoint, name, _gq);
            //Path path = new Path(arrow);
            //ListPath.Add(path);

            //return path;

            return null;
        }
       
        internal static bool GoOnNextCheckPoint(Path path)
        {

            path.LastCheckPoint = new Vector3(path.FirstCheckPoint.x, 
                                              path.FirstCheckPoint.y, 
                                              path.FirstCheckPoint.z);

            path.CheckPoints.RemoveFirst();

            if (path.CheckPoints.Count == 0)
            {
                GroundQuiver.RemovePath(path);

                return true;
            }

            return false;
        }

        public static void RemovePath(Path path)
        {
            //VectorLine.Destroy(ref path.Arrow.pathLine);
            ListPath.Remove(path);
        }


        
    }
}
